<template>
	<div>
		<div style="margin-bottom: 10px; text-align: left;">
			<div style="display: flex; flex-direction: row;justify-content: space-between;">
				<el-input
				  v-model="mathFormat"
				  style="max-width: 600px"
				  placeholder="请输入一元多次方程式"
				  class="input-with-select"
				>
				  <template #append>
					<el-button type="text" @click="drawFunctionLine">添加</el-button>
				  </template>
				</el-input>
				<div>
					<el-button type="text" @click="deleteObject()">删除</el-button>
					<el-button type="text" @click="isShowZb=!isShowZb" :style="{'color': isShowZb ? 'blue': 'black'}">坐标</el-button>
				</div>
			</div>
		</div>
		<div style="position: relative;">
			<div class="left-menus" style="width: 60px; display: flex; flex-direction: column;flex-wrap: wrap;justify-content: center;align-items: center;">
				<div style="width: 100%; text-align: center; background-color: rgba(0, 0, 0, 0.3);">工具</div>
				<flow-items v-model="selectedDrawShape"></flow-items>
			</div>
			<svg :id="flowId"
				class="svg-style"
				:viewBox="viewBox"
				@mouseleave="endMove"
				@mouseup="endMove" 
				@mousemove="moveObject"
				@mousedown="startDraw"
				@wheel="mouseWheel"
				@contextmenu.prevent="showMenu" xmlns="http://www.w3.org/2000/svg">
				<defs>
					<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="6" markerHeight="6" orient="auto">
						<path d="M 0 0 L 10 5 L 0 10 z" fill="black" />
					</marker>
				</defs>
  				<g tag="coordinate" v-if="isShowZb">  
					<g tag="coordinate-x">
						<polyline :points="coordinate.coordinateX.points" stroke="gray" stroke-width="2" stroke-dasharray="3 2"
						stroke-linecap="round" fill="none" stroke-linejoin="round"></polyline>
						<polyline :points="item" stroke="gray" stroke-width="2" stroke-dasharray="3 2"
						stroke-linecap="round" fill="none" stroke-linejoin="round" v-for="item in coordinate.coordinateX.kedu"></polyline>
					</g>
					<g tag="coordinate-y">
						<polyline :points="coordinate.coordinateY.points" stroke="gray" stroke-width="2" stroke-dasharray="3 2"
						stroke-linecap="round" fill="none" stroke-linejoin="round"></polyline>
						<polyline :points="item" stroke="gray" stroke-width="2" stroke-dasharray="3 2"
						stroke-linecap="round" fill="none" stroke-linejoin="round" v-for="item in coordinate.coordinateY.kedu"></polyline>
					</g>
					<g tag="coordinate-z">
						<!-- <polyline :points="coordinate.coordinateZ.points" stroke="gray" stroke-width="2" stroke-dasharray="3 2"
						stroke-linecap="round" fill="none" stroke-linejoin="round"></polyline> -->
					</g>
				</g>
				<g tag="mathDraw">
					<g v-for="(item, index) in lineContent.lines">
						<polyline :points="item.line" :stroke="item.fill" stroke-width="2"
						stroke-linecap="round" fill="none" stroke-linejoin="round" @click="selectedLine(item, index)">
						</polyline>
						<image :x="item.format.x" :y="item.format.y" @mousedown="selectObject(item, index, $event)" :href="item.format.img"></image>
					</g>
				</g>
				<g tag="shapeDraw">
					<g v-for="(item, index) in lineContent.shapes">
						<g v-if="item.type == shapes.line.id || item.type == shapes.lineArrow.id">
							<line v-if="item.type == shapes.line.id" @mousedown="selectObject(item, index, $event)"
							 :x1="item.x" :y1="item.y" :x2="item.x1" :y2="item.y1"
							 stroke="black" stroke-width="2" @dblclick="item.isInput=true" />
							<line v-if="item.type == shapes.lineArrow.id"  @dblclick="item.isInput=true"
							 :x1="item.x" :y1="item.y" :x2="item.x1" :y2="item.y1"  @mousedown="selectObject(item, index, $event)"
							  stroke="black" stroke-width="2" marker-end="url(#arrow)" />
							<text v-if="!item.isInput && item.text" @dblclick="item.isInput=true"
								:x="(item.x + item.x1)/2" :y="(item.y+item.y1)/2" font-size="16" fill="black">{{item.text}}</text>
							<foreignObject v-if="item.isInput"
								:x="(item.x + item.x1)/2" :y="(item.y+item.y1)/2 - 20" width="300" height="40">
								<el-input style="z-index: 10000;" @mousedown="inputForbid" v-model="item.text"  v-on:keyup.enter="item.isInput=false"></el-input>
							</foreignObject>
						</g>
						<g v-if="item.type == shapes.text.id">
							<text v-if="!item.isInput"
								@dblclick="item.isInput=true"  @mousedown="selectObject(item, index, $event)"
								:x="item.x" :y="item.y" font-size="16" fill="black">{{item.text}}</text>
							<foreignObject v-if="item.isInput"  @mousedown="selectObject(item, index, $event)"
								:x="item.x" :y="item.y -  20" width="300" height="40">
								<el-input style="z-index: 10000;" @mousedown="inputForbid" v-model="item.text"  v-on:keyup.enter="item.isInput=false"></el-input>
							</foreignObject>
						</g>
						<g v-if="item.type==shapes.ellipse.id">
							<ellipse v-if="item.type==shapes.ellipse.id"
								 fill="#FFFFFF" @dblclick="item.isInput=true"
								:cx="item.cx" :cy="item.cy" 
								:rx="item.rx" :ry="item.ry" stroke="black" stroke-width="2">
							</ellipse>
							<foreignObject @dblclick="item.isInput=true" @mousedown="selectObject(item, index, $event)"
								:x="item.cx - item.rx" :y="item.cy - item.ry + 10" :width="item.rx*2" :height="item.ry*2-5">
								<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; flex-direction: row; justify-content: center;align-items: center; width: 100%; height: 100%;">
									<span xmlns="http://www.w3.org/1999/xhtml" v-if="!item.isInput">{{item.text}}</span>
									<el-input style="z-index: 10000;" @mousedown="inputForbid" type="textarea" v-if="item.isInput" v-model="item.text"  v-on:keyup.enter="item.isInput=false"></el-input>
								</div>								
							</foreignObject>
						</g>
						<g v-if="item.type==shapes.rect.id">
							<rect @mousedown="selectObject(item, index, $event)" :x="item.x" :y="item.y" :width="item.width" :height="item.height" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></rect>
							<foreignObject @dblclick="item.isInput=true" @mousedown="selectObject(item, index, $event)"
								:x="item.x" :y="item.y" :width="item.width" :height="item.height">
								<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; flex-direction: row; justify-content: center;align-items: center; width: 100%; height: 100%;">
									<span xmlns="http://www.w3.org/1999/xhtml" v-if="!item.isInput">{{item.text}}</span>
									<el-input style="z-index: 10000;" @mousedown="inputForbid" type="textarea" v-if="item.isInput" v-model="item.text"  v-on:keyup.enter="item.isInput=false"></el-input>
								</div>								
							</foreignObject>
						</g>
						<g v-if="item.type==shapes.prismatic.id">
							<path :d="item.path" fill="#FFFFFF"  fill-opacity="0.5" stroke="black" stroke-width="2"  @mousedown="selectObject(item, index, $event)"></path>
							<foreignObject @dblclick="item.isInput=true"  @mousedown="selectObject(item, index, $event)"
								:x="item.x" :y="item.y" :width="item.width" :height="item.height">
								<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; flex-direction: row; justify-content: center;align-items: center; width: 100%; height: 100%;">
									<span xmlns="http://www.w3.org/1999/xhtml" v-if="!item.isInput">{{item.text}}</span>
									<el-input style="z-index: 10000;" type="textarea" v-if="item.isInput" v-model="item.text" @mousedown="inputForbid($event)"  v-on:keyup.enter="overInput(item, $event)"></el-input>
								</div>								
							</foreignObject>
						</g>
						<g v-if="item.type==shapes.triangle.id">
							<path :d="item.path" fill="#FFFFFF"  fill-opacity="0.5" stroke="black" stroke-width="2"  @mousedown="selectObject(item, index, $event)"></path>
						</g>
						<g v-if="item.type==shapes.pen.id">
							<path :d="item.path" fill="#FFFFFF"  fill-opacity="0.5" stroke="black" stroke-width="2"  @mousedown="selectObject(item, index, $event)"></path>
						</g>
					</g>
					<g v-if="isLine">
						<circle @mousedown="startMove('start', $event)" :cx="xZObj.x" :cy="xZObj.y" r="10" stroke="black" stroke-width="2" fill="#FFFFFF" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('end', $event)" :cx="xZObj.x1" :cy="xZObj.y1" r="10" stroke="black" stroke-width="2" fill="#FFFFFF" fill-opacity="0.5"></circle>
					</g>
					<g v-else-if="isTriangle">
						<circle @mousedown="startMove('f', $event)" :cx="xZObj.x1" :cy="xZObj.y1" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('s', $event)" :cx="xZObj.x2" :cy="xZObj.y2" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('t', $event)" :cx="xZObj.x3" :cy="xZObj.y3" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
					</g>
					<g v-else-if="isRect">
						<circle @mousedown="startMove('lt', $event)" :cx="xZObj.x" :cy="xZObj.y" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('rt', $event)" :cx="xZObj.x + xZObj.width" :cy="xZObj.y" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('rb', $event)" :cx="xZObj.x + xZObj.width" :cy="xZObj.y + xZObj.height" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
						<circle @mousedown="startMove('lb', $event)" :cx="xZObj.x" :cy="xZObj.y + xZObj.height" r="10" fill="#FFFFFF" stroke="black" stroke-width="2" fill-opacity="0.5"></circle>
					</g>
				</g>
			</svg>
		</div>
	</div>
	<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
		<button @click="submitData(true)">取消</button>
		<button @click="submitData(false)">插入</button>
	</div>
</template>

<script>
	import { v4 as uuidv4 } from 'uuid'
	import $ from 'jquery'
	import MathFunction from './plugins/MathFunction.js'
	import './plugins/mathjax.js'
	import 'mathjax/es5/tex-svg'
	import {ElInput, ElButton} from 'element-plus'
	import 'element-plus/dist/index.css'
	import shapes from './utils/ShapeColle.js'
	import FlowItems from './module/FlowItems.vue'
	import ShapeMove from './plugins/ShapeMove.js'
	export default {
		name: 'HtaoFlow',
		title: 'htao-flow',
		order: 2,
		props: {
			modelValue: {
				type: Object,
				default: () => null
			},
			invokeMethod: {
				type: Function,
				default: () => {return (flowJson, svg, imgBase64, isSubmit) => {}}
			},
			width: {
				type: String,
				default: () => '100%'
			},
			height: {
				type: String,
				default: () => "400px"
			}
		},
		emits: ['update:modelValue'],
		components: {
			ElInput,ElButton,FlowItems
		},
		watch: {
			modelValue: {
				handler(newValue, oldValue) {
					if (newValue && this.lineContent != newValue) {
						this.lineContent = newValue;
						if (!this.lineContent) {
							this.lineContent = {
								type: 'math',
								lines: []
							};
						}
					}
				},
				immediate: true,
				deep: true
			},
		},
		data() {
			return {
				lineContent: {
					type: 'math',
					lines: [],
					shapes:[]
				},
				flowId: uuidv4().replaceAll(/-/g, ''),
				coordinate: {
					coordinateX: {
						points: "",
						kedu: []
					},
					coordinateY: {
						points: "",
						kedu: []
					},
					coordinateZ: {
						points: ""
					}
				},
				svgWidth: 0,
				svgHeight: 0,
				zoom: 20,
				functionLine: [],
				view: "",
				mathFunction: null,
				selectItem: null,
				beforeX: 0,
				beforeY: 0,
				viewBox: "0 0 1 1",
				mathFormat: '',
				selectedFun: null,
				selectedInd: null,
				shapes: shapes,
				selectedDrawShape: '',
				shapeMove: null,
				selectedLineShape: null,
				isLine: false,
				isTriangle: false,
				isRect: false,
				xZObj: null,
				xZInd: null,
				isShowZb: false,
				viewBoxWidth: 1,
				viewBoxHeight: 1
			}
		},
		mounted() {
			let _this = this;
			setTimeout(() => {
				this.viewBoxWidth = $("#" + _this.flowId).width();
				this.viewBoxHeight = $("#" + _this.flowId).height();
				_this.viewBox = "0 0 " + this.viewBoxWidth + " " + this.viewBoxHeight;
				this.svgWidth = this.viewBoxWidth;
				this.svgHeight = this.viewBoxHeight;
				_this.mathFunction = new MathFunction(this.viewBoxWidth, this.viewBoxHeight, _this.zoom, _this.coordinate);
				_this.mathFunction.getCoordinateX();
				_this.mathFunction.getCoordinateY();
				setTimeout(() => {MathJax.typesetPromise();}, 200)
			}, 100)
			this.shapeMove = new ShapeMove();
		},
		methods: {
			mouseWheel(event) {
				event.preventDefault();
				let delta = event.deltaY;
				this.viewBoxWidth = this.viewBoxWidth + delta;
				this.viewBoxHeight = this.viewBoxHeight + delta;
				this.viewBox = '0 0 ' + this.viewBoxWidth + ' ' + this.viewBoxHeight;
				this.coordinate.coordinateX = {
					points: "",
					kedu: []
				};
				this.coordinate.coordinateY = {
					points: "",
					kedu: []
				};
				this.coordinate.coordinateZ = {
					points: "",
					kedu: []
				};
				this.mathFunction = new MathFunction(this.viewBoxWidth, this.viewBoxHeight, this.zoom, this.coordinate);
				this.mathFunction.getCoordinateX();
				this.mathFunction.getCoordinateY();
				let lines = [];
				let len = this.lineContent.lines.length;
				for(let i = 0; i < len; i++) {
					let t = this.drawFunction(this.lineContent.lines[i].format.con);
					if (t == '') {
						continue;
					}
					lines.push(t);
				}
				this.lineContent.lines = lines;
			},
			drawFunctionLine() {
				let t = this.drawFunction(this.mathFormat);
				if (t == '') return;
				this.lineContent.lines.push(t);
			},
			drawFunction(mathFormat) {
				let t = this.mathFunction.drawLine(mathFormat);
				if (t == '') return '';
				let svg = MathJax.tex2svg(t.format.con, {display: true});
				let svgText = svg.firstChild.outerHTML;
				t.format.img = this.generatorSvgBase64(svgText);
				return t;
			},
			generatorSvgBase64(html) {
				let svg64 = btoa(unescape(encodeURIComponent(html)));
				let image64 = 'data:image/svg+xml;base64,' + svg64;
				return image64;
			},
			submitData(isCancel) {
				this.xZObj = {};
				this.xZInd = null;
				this.updateStatus();
				let _this = this;
				setTimeout(() => {
					let html = document.getElementById(_this.flowId).outerHTML;
					_this.invokeMethod(_this.lineContent, html, _this.generatorSvgBase64(html), isCancel)
				}, 100)
			},
			selectObject(item, index, e) {
				this.xZObj = item;
				this.xZInd = index;
				this.updateStatus();
				this.shapeMove.selectedObject(this.xZObj, e, this.xZObj.type);
			},
			updateStatus() {
				this.isLine = this.xZObj.type == shapes.line.id || this.xZObj.type==shapes.lineArrow.id;
				this.isTriangle = this.xZObj.type == shapes.triangle.id;
				this.isRect = this.xZObj.type == shapes.prismatic.id || this.xZObj.type == shapes.rect.id || this.xZObj.type == shapes.ellipse.id;
			},
			moveObject(e) {
				this.shapeMove.moveOrStrachObject(e);
			},
			startMove(orign, e) {
				this.shapeMove.startMoveObject(e, orign, this.xZObj);
			},
			endMove(e) {
				this.shapeMove.endMoveOrStrachObject(e);
			},
			showMenu() {},
			selectedLine(line, index) {
				if (this.selectedFun) {
					this.selectedFun.fill="black";
				}
				line.fill="green"
				this.selectedFun = line;
				this.selectedInd = index;
			},
			deleteObject() {
				if (this.selectedFun) {
					this.lineContent.lines.splice(this.selectedInd, 1);
					this.selectedFun = null;
					this.selectedInd = null;
				}
				if (this.xZInd != null) {
					this.lineContent.shapes.splice(this.xZInd, 1);
					this.xZObj = {};
					this.xZInd = null;
					this.updateStatus();
				}
			},
			startDraw(e) {
				let svg = document.getElementById(this.flowId);
				let ctm = svg.getScreenCTM();
				var point = svg.createSVGPoint();
				point.x = e.clientX;
				point.y = e.clientY;
				var mousePoint = point.matrixTransform(ctm.inverse());
				let currentX = mousePoint.x;
				let currentY = mousePoint.y;
				// alert(this.selectedDrawShape)
				if(this.xZObj && this.xZObj.type == 'lineArrow') {
					if (this.xZObj.x == this.xZObj.x1 && this.xZObj.y == this.xZObj.y1) {
						this.deleteObject();
					}
				}
				let line = this.shapeMove.initDrawLine(currentX, currentY, this.lineContent.shapes, this.selectedDrawShape, e);
				if (line) {
					this.xZObj = line;
					this.xZInd = this.lineContent.shapes.length - 1;
					this.updateStatus();
				} else {
					this.xZObj = {};
					this.xZInd = null;
					this.updateStatus();
				}
			},
			hidenOpr() {
				for(let i = 0; i < this.lineContent.shapes.length; i++) {
					this.lineContent.shapes[i].isOpr = false;
					this.lineContent.shapes[i].isInput = false;
				}
			},
			inputForbid(event) {
				$(event.target).focus()
				event.stopPropagation();
				event.preventDefault();
			},
			overInput(item, event) {
				item.isInput=false;
				event.stopPropagation();
				event.preventDefault();
			}
		},
	}
</script>

<style scoped>
	.svg-style {
		width: 100%;
		height: 400px;
		box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5),
			-1px 1px 1px rgba(0, 0, 0, 0.5),
			-1px -1px 1px rgba(0, 0, 0, 0.5);
	}
	.line-style {
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
		width: 40px;
		height: 40px;
	}
	.left-menus {
		box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5),
			-1px 1px 1px rgba(0, 0, 0, 0.5);
		position: absolute;
		top: 0;
		left: 1px;
		background-color: rgba(255, 255, 255, 0.3);
	}
</style>